/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Boundary;

import Control.*;
import Entity.*;
import fr.umlv.zen3.Application;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Random;
import java.util.function.Consumer;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.World;

/**
 *
 * @author Maravillas
 */
public class BoundarySpaceShip {

    private ToCreateWorld toCreateWorld = new ToCreateWorld();
    private EnemyBagel enemyBagel;
    private EnemyElongatedSpiral enemyElongSpiral;
    private EnemyLadyBug enemyLadyBug;
    private EnemySpiral enemySpiral;
    private EnemyRectangle enemyRectangle;
    private ArrayList<Bullet> bullets;
    private ArrayList<Bomb> bombs;
    private World world;

    public void init(int WIDTH, int HEIGHT) {

        float timeStep = 1.0f / 60f;
        int velocityIteration = 6;
        int positionIteration = 2;
        toCreateWorld = new ToCreateWorld();
        world = toCreateWorld.createWorld();
        ArrayList<Vec2> starts = toCreateWorld.createStarts(WIDTH, HEIGHT);
        ArrayList<Planet> planets = toCreateWorld.createPlanets(WIDTH, HEIGHT);
        SpaceShip spaceShip = toCreateWorld.createSpaceShip(WIDTH, HEIGHT);
        bullets = new ArrayList<>();
        bombs = new ArrayList<>();
        ToTurn turn = new ToTurn(spaceShip);
        ToShoot shoot = new ToShoot();
        ToWardOff wardOff = new ToWardOff();
        ToBomb toBomb = new ToBomb();
        world.setContactListener(toCreateWorld.createContactListener());
        //Window
        Application.run("Master Pilot", WIDTH, HEIGHT, turn, shoot, wardOff, toBomb, toCreateWorld, context -> {
            for (;;) {

                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                context.render(new Consumer<Graphics2D>() {

                    @Override
                    public void accept(Graphics2D graphics) {

                        if (toCreateWorld.getHealth() > 0 && toCreateWorld.getNumberEnemy() != 0) {
//Background
                            graphics.setColor(Color.BLACK);
                            graphics.fill(new Rectangle2D.Float(0, 0, WIDTH, HEIGHT));

//Motion effect
                            float x = spaceShip.getBody().getPosition().x;
                            float y = spaceShip.getBody().getPosition().y;
                            graphics.translate(-x + WIDTH / 2, -y + HEIGHT / 2);

//Paint starts
                            graphics.setColor(Color.WHITE);
                            for (Vec2 point : starts) {
                                graphics.fill(new Ellipse2D.Float(point.x, point.y, 4, 4));
                                graphics.fill(new Ellipse2D.Float(-point.x, -point.y, 4, 4));
                                graphics.fill(new Ellipse2D.Float(-point.x, point.y, 4, 4));
                                graphics.fill(new Ellipse2D.Float(point.x, -point.y, 4, 4));
                            }
//SPACE SHIP
                            //To ward off, shield
                            if (wardOff.isShield()) {
                                graphics.setColor(Color.YELLOW);
                                graphics.fill(new Ellipse2D.Float(x - spaceShip.getShape().m_radius, y - spaceShip.getShape().m_radius, spaceShip.getShape().m_radius * 2, spaceShip.getShape().m_radius * 2));
                                toCreateWorld.setHealth(6);
                            }
                            graphics.setColor(Color.RED);
                            graphics.fill(new Polygon(turn.paintX(turn.getTurn(), x, y, WIDTH, HEIGHT), turn.paintY(turn.getTurn(), x, y, WIDTH, HEIGHT), 3));
                            //Apply Linear Impulse, motion space ship
                            if (turn.getTurn()[0] == 0 & turn.getTurn()[1] == 0) {
                                spaceShip.getBody().setLinearVelocity(new Vec2(0, 0));
                            } else {
                                spaceShip.getBody().applyLinearImpulse(new Vec2(turn.getTurn()[0], turn.getTurn()[1]), spaceShip.getBody().getWorldPoint(spaceShip.getBody().getWorldCenter()));
                            }
                            
//Square of health and health of enemy
                            graphics.setColor(Color.LIGHT_GRAY);
                            graphics.fill(new Rectangle2D.Float(x+170, y-280, 180, 40));
                            graphics.setColor(Color.MAGENTA);
                            graphics.drawString("Healt: ", x+175, y-265);
                            for (int i = 0; i < toCreateWorld.getHealth(); i++) {
                                graphics.drawString("♥", x+215 +i*12, y-265);
                            }
                            graphics.setColor(Color.GREEN);
                            graphics.drawString("Enemy: ", x+175, y-250);
                            for (int i = 0; i < toCreateWorld.getHealthEnemy(); i++) {
                                graphics.drawString("◙", x+215 +i*12, y-250);
                            }
                            //To shoot
                            if (shoot.isBullet()) {

                                Bullet bullet = toCreateWorld.createBullet(turn.paintX(turn.getTurn(), x, y, WIDTH, HEIGHT)[0], turn.paintY(turn.getTurn(), x, y, WIDTH, HEIGHT)[0], new Vec2(shoot.getDirection()[0], shoot.getDirection()[1]));
                                shoot.setBullet(false);
                                bullets.add(bullet);
                            }
//Paint bullets
                            graphics.setColor(Color.MAGENTA);
                            for (Bullet bullet : bullets) {
                                graphics.fill(new Ellipse2D.Float(bullet.getBody().getWorldCenter().x, bullet.getBody().getWorldCenter().y, bullet.getShape().m_radius * 2, bullet.getShape().m_radius * 2));
                                bullet.getBody().applyLinearImpulse(bullet.getDirection(), bullet.getBody().getWorldPoint(bullet.getBody().getWorldCenter()));
                            }

                            //To Bomb
                            if (toBomb.isBomb()) {
                                Bomb bomb = toCreateWorld.createBomb(turn.paintX(turn.getTurn(), x, y, WIDTH, HEIGHT)[0], turn.paintY(turn.getTurn(), x, y, WIDTH, HEIGHT)[0], new Vec2(toBomb.getDirection()[0], toBomb.getDirection()[1]));
                                toBomb.setBomb(false);
                                bombs.add(bomb);
                            }
                            //Paint bombs                        
                            for (Bomb bomb : bombs) {
                                graphics.setColor(Color.GRAY);
                                graphics.fill(new Ellipse2D.Float(bomb.getBody().getWorldCenter().x, bomb.getBody().getWorldCenter().y, bomb.getShape().m_radius * 2, bomb.getShape().m_radius * 2));
                                graphics.setColor(Color.LIGHT_GRAY);
                                graphics.fill(new Ellipse2D.Float(bomb.getBody().getWorldCenter().x + 10, bomb.getBody().getWorldCenter().y + 10, bomb.getShape().m_radius * 2 - 10, bomb.getShape().m_radius * 2 - 10));
                                bomb.getBody().applyLinearImpulse(bomb.getDirection(), bomb.getBody().getWorldPoint(bomb.getBody().getWorldCenter()));
                            }

//Destroy bodies
                            Bullet bullet1 = new Bullet();
                            Bullet bullet2 = new Bullet();
                            Bullet bullet3 = new Bullet();
                            Bomb bomb1 = new Bomb();
                            for (Bullet bullet : bullets) {
                                for (int i = 0; i < toCreateWorld.getPlanetBulletCollided().size(); i++) {
                                    if (bullet.getBody().equals(toCreateWorld.getPlanetBulletCollided().get(i))) {
                                        bullet1 = bullet;
                                        world.destroyBody(toCreateWorld.getPlanetBulletCollided().get(i));
                                        toCreateWorld.setPlanetBulletCollided(i);
                                    }
                                }

                                for (int i = 0; i < toCreateWorld.getEnemyBulletCollided().size(); i++) {
                                    if (bullet.getBody().equals(toCreateWorld.getEnemyBulletCollided().get(i))) {
                                        bullet3 = bullet;
                                        world.destroyBody(toCreateWorld.getEnemyBulletCollided().get(i));
                                        toCreateWorld.setEnemyBulletCollided(i);
                                    }
                                }

                                for (int i = 0; i < toCreateWorld.getSpaceShipBulletCollided().size(); i++) {
                                    if (bullet.getBody().getUserData() == "bulletEnemy" && bullet.getBody().equals(toCreateWorld.getSpaceShipBulletCollided().get(i))) {
                                        bullet2 = bullet;
                                        world.destroyBody(toCreateWorld.getSpaceShipBulletCollided().get(i));
                                        toCreateWorld.setSpaceShipBulletCollided(i);
                                    }
                                }
                            }
                            for (Bomb bomb : bombs) {
                                for (int i = 0; i < toCreateWorld.getEnemyBombCollided().size(); i++) {
                                    if (bomb.getBody().equals(toCreateWorld.getEnemyBombCollided().get(i))) {
                                        bomb1 = bomb;
                                        world.destroyBody(toCreateWorld.getEnemyBombCollided().get(i));
                                        toCreateWorld.setEnemyBombCollided(i);
                                    }
                                }
                            }
                            bombs.remove(bomb1);
                            bullets.remove(bullet1);
                            bullets.remove(bullet2);
                            bullets.remove(bullet3);

//PLANET
                            Planet planet1 = new Planet();
                            for (Planet planet : planets) {
                                //Destroy bodies
                                for (int i = 0; i < toCreateWorld.getPlanetBulletCollided().size(); i++) {
                                    if (planet.getBody().equals(toCreateWorld.getPlanetBulletCollided().get(i))) {
                                        planet1 = planet;
                                        world.destroyBody(toCreateWorld.getPlanetBulletCollided().get(i));
                                        toCreateWorld.setPlanetBulletCollided(i);
                                    }
                                }
                                graphics.setColor(planet.getColor());
                                planet.getBody().setLinearVelocity(new Vec2(0, 0));
                                graphics.fill(new Ellipse2D.Float(planet.getBody().getPosition().x - planet.getShape().m_radius, planet.getBody().getPosition().y - planet.getShape().m_radius, planet.getShape().m_radius * 2, planet.getShape().m_radius * 2));
                            }
                            planets.remove(planet1);

//ENEMIES
                            int xEnemy;
                            int yEnemy;
                            int radiusEnemy;
                            switch (toCreateWorld.getNumberEnemy()) {
                                case 0:
                                    /*//Background
                                     graphics.setColor(Color.BLACK);
                                     graphics.fill(new Rectangle2D.Float(0, 0, WIDTH, HEIGHT));
                                     graphics.setColor(Color.MAGENTA);
                                     graphics.drawString("WINNER", x, y);
                                     try {
                                     Thread.sleep(500);
                                     } catch (InterruptedException e) {
                                     Thread.currentThread().interrupt();
                                     }*/
                                    break;

                                case 1:
                                    //Enemy SPIRAL
                                    if (toCreateWorld.isCreated()) {
                                        createEnemySpiral(WIDTH, HEIGHT);
                                        toCreateWorld.setCreated(false);
                                    }
                                    if (toCreateWorld.getHealthEnemy() > 0) {
                                        graphics.setColor(Color.GREEN);
                                        xEnemy = (int) (enemySpiral.getBody().getPosition().x - enemySpiral.getShape().m_radius);
                                        yEnemy = (int) (enemySpiral.getBody().getPosition().y - enemySpiral.getShape().m_radius);
                                        radiusEnemy = (int) enemySpiral.getShape().m_radius * 2;
                                        graphics.drawArc(xEnemy, yEnemy, radiusEnemy, radiusEnemy, 0, 180);
                                        graphics.drawArc(xEnemy, yEnemy, radiusEnemy - 10, radiusEnemy - 10, 0, -180);
                                        graphics.drawArc(xEnemy + 10, yEnemy + 10, radiusEnemy - 20, radiusEnemy - 20, 0, 180);
                                        graphics.drawArc(xEnemy + 10, yEnemy + 10, radiusEnemy - 30, radiusEnemy - 30, 0, -180);
                                        graphics.drawArc(xEnemy + 20, yEnemy + 20, radiusEnemy - 40, radiusEnemy - 40, 0, 180);
                                        turn.motionEnemy(x, y, enemySpiral.getBody().getPosition().x, enemySpiral.getBody().getPosition().y);

                                        //To shoot enemy and delay
                                        if (toCreateWorld.getDelay() < 100) {
                                            toCreateWorld.setDelay(toCreateWorld.getDelay() + 1);
                                            enemySpiral.getBody().applyLinearImpulse(turn.getForces(), enemySpiral.getBody().getWorldPoint(enemySpiral.getBody().getWorldCenter()));
                                        } else {
                                            toCreateWorld.setDelay(0);
                                            Bullet bulletEnemy = toCreateWorld.createBulletEnemy((int) enemySpiral.getBody().getPosition().x, (int) enemySpiral.getBody().getPosition().y, new Vec2(turn.getForces()));
                                            bullets.add(bulletEnemy);
                                        }
                                    } else {
                                        toCreateWorld.setNumberEnemy(2);
                                        toCreateWorld.setHealthEnemy(5);
                                        toCreateWorld.setCreated(true);
                                        world.destroyBody(enemySpiral.getBody());
                                        destroyBullets();
                                    }
                                    break;

                                case 2:
                                    //Enemy RECTANGLE
                                    if (toCreateWorld.isCreated()) {
                                        createEnemyRectangle(WIDTH, HEIGHT);
                                        toCreateWorld.setCreated(false);
                                    }
                                    if (toCreateWorld.getHealthEnemy() > 0) {
                                        graphics.setColor(Color.BLUE);
                                        radiusEnemy = (int) enemyRectangle.getShape().m_radius;
                                        xEnemy = (int) (enemyRectangle.getBody().getPosition().x - radiusEnemy);
                                        yEnemy = (int) (enemyRectangle.getBody().getPosition().y - radiusEnemy);
                                        graphics.drawRect(xEnemy, yEnemy, radiusEnemy * 2, radiusEnemy);
                                        turn.motionEnemy(x, y, enemyRectangle.getBody().getPosition().x, enemyRectangle.getBody().getPosition().y);

                                        //To shoot enemy and delay
                                        if (toCreateWorld.getDelay() < 100) {
                                            toCreateWorld.setDelay(toCreateWorld.getDelay() + 1);
                                            enemyRectangle.getBody().applyLinearImpulse(turn.getForces(), enemyRectangle.getBody().getWorldPoint(enemyRectangle.getBody().getWorldCenter()));
                                        } else {
                                            toCreateWorld.setDelay(0);
                                            Bullet bulletEnemy = toCreateWorld.createBulletEnemy((int) enemyRectangle.getBody().getPosition().x, (int) enemyRectangle.getBody().getPosition().y, new Vec2(turn.getForces()));
                                            bullets.add(bulletEnemy);
                                        }
                                    } else {
                                        toCreateWorld.setNumberEnemy(3);
                                        toCreateWorld.setHealthEnemy(6);
                                        toCreateWorld.setCreated(true);
                                        world.destroyBody(enemyRectangle.getBody());
                                        destroyBullets();
                                    }
                                    break;

                                case 3:
                                    //Enemy Lady Bug
                                    if (toCreateWorld.isCreated()) {
                                        createEnemyLadyBug(WIDTH, HEIGHT);
                                        toCreateWorld.setCreated(false);
                                    }
                                    if (toCreateWorld.getHealthEnemy() > 0) {
                                        radiusEnemy = (int) enemyLadyBug.getShape().m_radius;
                                        xEnemy = (int) (enemyLadyBug.getBody().getPosition().x - radiusEnemy);
                                        yEnemy = (int) (enemyLadyBug.getBody().getPosition().y - radiusEnemy);
                                        graphics.setColor(Color.RED);
                                        graphics.fill(new Ellipse2D.Float(xEnemy, yEnemy, radiusEnemy * 2, radiusEnemy * 2));
                                        graphics.setColor(Color.BLACK);
                                        Random random = new Random(0);
                                        for (int i = 0; i < 20; i++) {
                                            graphics.fill(new Ellipse2D.Float(xEnemy + i * random.nextInt(radiusEnemy / 4),
                                                    yEnemy + i * random.nextInt(radiusEnemy / 4), radiusEnemy / 5, radiusEnemy / 5));
                                        }

                                        turn.motionEnemy(x, y, enemyLadyBug.getBody().getPosition().x, enemyLadyBug.getBody().getPosition().y);

                                        //To shoot enemy and delay
                                        if (toCreateWorld.getDelay() < 100) {
                                            toCreateWorld.setDelay(toCreateWorld.getDelay() + 1);
                                            enemyLadyBug.getBody().applyLinearImpulse(turn.getForces(), enemyLadyBug.getBody().getWorldPoint(enemyLadyBug.getBody().getWorldCenter()));
                                        } else {
                                            toCreateWorld.setDelay(0);
                                            Bullet bulletEnemy = toCreateWorld.createBulletEnemy((int) enemyLadyBug.getBody().getPosition().x, (int) enemyLadyBug.getBody().getPosition().y, new Vec2(turn.getForces()));
                                            bullets.add(bulletEnemy);
                                        }
                                    } else {
                                        toCreateWorld.setNumberEnemy(4);
                                        toCreateWorld.setHealthEnemy(8);
                                        world.destroyBody(enemyLadyBug.getBody());
                                        toCreateWorld.setCreated(true);
                                        destroyBullets();
                                    }
                                    break;
                                case 4:
                                    //Enemy Elongated Spiral
                                    if (toCreateWorld.isCreated()) {
                                        createEnemyElongatedSpiral(WIDTH, HEIGHT);
                                        toCreateWorld.setCreated(false);
                                    }
                                    if (toCreateWorld.getHealthEnemy() > 0) {
                                        radiusEnemy = (int) enemyElongSpiral.getShape().m_radius;
                                        xEnemy = (int) (enemyElongSpiral.getBody().getPosition().x - radiusEnemy);
                                        yEnemy = (int) (enemyElongSpiral.getBody().getPosition().y - radiusEnemy);
                                        graphics.setColor(Color.MAGENTA);
                                        for (int i = 0; i < 5; i++) {
                                            graphics.drawOval(xEnemy + i * 10, yEnemy + i * 10,
                                                    radiusEnemy + i * 10, radiusEnemy + i * 10);
                                        }
                                        turn.motionEnemy(x, y, enemyElongSpiral.getBody().getPosition().x, enemyElongSpiral.getBody().getPosition().y);

                                        //To shoot enemy and delay
                                        if (toCreateWorld.getDelay() < 100) {
                                            toCreateWorld.setDelay(toCreateWorld.getDelay() + 1);
                                            enemyElongSpiral.getBody().applyLinearImpulse(turn.getForces(), enemyElongSpiral.getBody().getWorldPoint(enemyElongSpiral.getBody().getWorldCenter()));
                                        } else {
                                            toCreateWorld.setDelay(0);
                                            Bullet bulletEnemy = toCreateWorld.createBulletEnemy((int) enemyElongSpiral.getBody().getPosition().x, (int) enemyElongSpiral.getBody().getPosition().y, new Vec2(turn.getForces()));
                                            bullets.add(bulletEnemy);
                                        }
                                    } else {
                                        toCreateWorld.setNumberEnemy(5);
                                        toCreateWorld.setHealthEnemy(10);
                                        toCreateWorld.setCreated(true);
                                        world.destroyBody(enemyElongSpiral.getBody());
                                        destroyBullets();
                                    }
                                    break;

                                case 5:
                                    //Enemy Bagel
                                    if (toCreateWorld.isCreated()) {
                                        createEnemyBagel(WIDTH, HEIGHT);
                                        toCreateWorld.setCreated(false);
                                    }
                                    if (toCreateWorld.getHealthEnemy() > 0) {
                                        radiusEnemy = (int) enemyBagel.getShape().m_radius;
                                        xEnemy = (int) (enemyBagel.getBody().getPosition().x - radiusEnemy);
                                        yEnemy = (int) (enemyBagel.getBody().getPosition().y - radiusEnemy);
                                        graphics.setColor(Color.PINK);
                                        graphics.fill(new Ellipse2D.Float(xEnemy, yEnemy, radiusEnemy * 2, radiusEnemy * 2));
                                        graphics.setColor(Color.BLACK);
                                        graphics.fill(new Ellipse2D.Float(xEnemy + radiusEnemy / 2, yEnemy + radiusEnemy / 2, radiusEnemy, radiusEnemy));
                                        turn.motionEnemy(x, y, enemyBagel.getBody().getPosition().x, enemyBagel.getBody().getPosition().y);

                                        //To shoot enemy and delay
                                        if (toCreateWorld.getDelay() < 100) {
                                            toCreateWorld.setDelay(toCreateWorld.getDelay() + 1);
                                            enemyBagel.getBody().applyLinearImpulse(turn.getForces(), enemyBagel.getBody().getWorldPoint(enemyBagel.getBody().getWorldCenter()));
                                        } else {
                                            toCreateWorld.setDelay(0);
                                            Bullet bulletEnemy = toCreateWorld.createBulletEnemy((int) enemyBagel.getBody().getPosition().x, (int) enemyBagel.getBody().getPosition().y, new Vec2(turn.getForces()));
                                            bullets.add(bulletEnemy);
                                        }
                                    } else {
                                        toCreateWorld.setNumberEnemy(0);
                                        toCreateWorld.setHealthEnemy(0);
                                        world.destroyBody(enemyBagel.getBody());
                                        destroyBullets();
                                    }
                                    break;
                            }

                            //Step and dispose
                            graphics.dispose();
                            world.step(timeStep, velocityIteration, positionIteration);
                        } else {
                            if(toCreateWorld.getNumberEnemy()==0){
                                //WINNER
                                     graphics.setColor(Color.BLACK);
                                     graphics.fill(new Rectangle2D.Float(0, 0, WIDTH, HEIGHT));
                                     graphics.setColor(Color.MAGENTA);
                                     graphics.drawString("WINNER", 400, 300);
                                     graphics.setColor(Color.MAGENTA);
                                     graphics.drawString("PLAY AGAIN: PRESS ENTER", 350, 320);
                            }else {
                                //GAME OVER
                                     graphics.setColor(Color.BLACK);
                                     graphics.fill(new Rectangle2D.Float(0, 0, WIDTH, HEIGHT));
                                     graphics.setColor(Color.MAGENTA);
                                     graphics.drawString("GAME OVER", 400, 300);
                                     graphics.setColor(Color.MAGENTA);
                                     graphics.drawString("PLAY AGAIN: PRESS ENTER", 350, 320);
                            }  
                        }
                            
                    }
                });
            }
        });
    }

    public void createEnemyBagel(int WIDTH, int HEIGHT) {
        enemyBagel = toCreateWorld.createEnemyBagel(WIDTH, WIDTH);
    }

    public void createEnemyElongatedSpiral(int WIDTH, int HEIGHT) {
        enemyElongSpiral = toCreateWorld.createEnemyElogatedSpiral(WIDTH, WIDTH);
    }

    public void createEnemyLadyBug(int WIDTH, int HEIGHT) {
        enemyLadyBug = toCreateWorld.createEnemyLadyBug(WIDTH, WIDTH);
    }

    public void createEnemyRectangle(int WIDTH, int HEIGHT) {
        enemyRectangle = toCreateWorld.createEnemyRetangle(WIDTH, WIDTH);
    }

    public void createEnemySpiral(int WIDTH, int HEIGHT) {
        enemySpiral = toCreateWorld.createEnemySpiral(WIDTH, HEIGHT);
    }

    public void destroyBullets() {
        for (Bullet bullet : bullets) {
            world.destroyBody(bullet.getBody());
        }
        bullets.clear();
    }

}
